package com.youku.expression;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.youku.component.Project;
import com.youku.component.ProjectHolder;
import com.youku.component.procedure.HttpProcedure;
import com.youku.component.procedure.Procedure;
import com.youku.component.result.ExecuteResult;
import com.youku.component.result.HttpExecuteResult;
import com.youku.component.result.QueryExecuteResult;
import com.youku.component.result.UpdateExecuteResult;
import com.youku.exception.ExpressionException;
import com.youku.exception.NotRecognizedTagException;
import com.youku.util.Assert;

/**
 * 获取数据库请求或者http请求结果信息的表达式
 * 
 * @author loda
 *
 */
public class ResultInterpreter implements Interpreter {

	private String procedureId;

	private int index = 1;

	private String resultType;

	private String field;

	private static final Set<String> supportedSymbol;

	// private static final Logger logger =
	// LoggerFactory.getLogger(ResultInterpreter.class);
	//
	// private static final int MAX_RETRY_TIME;

	static {
		supportedSymbol = new HashSet<>();
		supportedSymbol.add("query");
		supportedSymbol.add("update");
		supportedSymbol.add("status");
		supportedSymbol.add("cookie");
		supportedSymbol.add("body");

		// MAX_RETRY_TIME =
		// Integer.parseInt(PropertyReader.read(Consts.MAX_RETRY));
	}

	@Override
	public Object interpreter(Position position, String input) {
		Assert.isCase(position);
		Project project = ProjectHolder.get(position.getProjectId());

		analysis(input);

		Procedure procedure = project.getProcedure(position, procedureId);

		ExecuteResult result = procedure.getResult(index);

		if (!supportedSymbol.contains(resultType)) {
			throw new NotRecognizedTagException(resultType + "为无法识别的标签");
		}
		switch (resultType) {
		case "query":
			return getQueryResult(result);
		case "update":
			return getUpdateResult(result);
		default:
			return getHttpResult(result, procedure);
		}

	}

	private String getHttpResult(ExecuteResult result, Procedure procedure) {
		HttpExecuteResult httpResult = (HttpExecuteResult) result;
		HttpProcedure httpProcedure = (HttpProcedure) procedure;
		switch (resultType) {
		case "status":
			return getHttpStatus(httpResult);
		case "cookie":
			return getHttpCookie(httpResult);
		case "body":
			return getHttpBody(httpResult, httpProcedure);
		default:
			throw new NotRecognizedTagException(resultType + "为无法识别的标签");
		}
	}

	private String getHttpCookie(HttpExecuteResult httpResult) {
		return httpResult.getCookieByKey(field);
	}

	private String getHttpStatus(HttpExecuteResult httpResult) {
		return httpResult.getResponseStatus();
	}

	private String getHttpBody(HttpExecuteResult httpResult, HttpProcedure httpProcedure) {
		// while (true) {
		// try {
		// return httpResult.getResponseBodyByField(field);
		// } catch (RetryException e) {
		// httpProcedure.retry();// 重试计数
		//
		// if (httpProcedure.getRetryTime() > MAX_RETRY_TIME) {
		// throw new AssertException("响应体拿不到数据。重试次数超过最大次数" + MAX_RETRY_TIME +
		// "，不再重试，该测试用例失败");
		// }
		// logger.info("第{}次重试", httpProcedure.getRetryTime());
		// try {
		// Thread.sleep(Consts.DELAY_TIME*1000);
		// } catch (InterruptedException e1) {
		// e1.printStackTrace();
		// }
		//
		// httpProcedure.run();
		//
		// httpResult = (HttpExecuteResult) httpProcedure.getResult(index);
		// }
		// }

		return httpResult.getResponseBodyByField(field);
	}

	private int getUpdateResult(ExecuteResult result) {
		return ((UpdateExecuteResult) result).getExecuteUpdate();
	}

	private String getQueryResult(ExecuteResult result) {
		return ((QueryExecuteResult) result).findByField(field);
	}

	private void analysis(String input) {
		String[] arr = StringUtils.split(input, ':');

		if (arr.length == 2) {
			field = arr[1];
		}

		arr = StringUtils.split(arr[0], '.');

		if (arr.length != 2)
			throw new ExpressionException("表达式左侧只有一个'.'");

		String idWithIndex = arr[0];

		int start = idWithIndex.indexOf('[');

		int offset = idWithIndex.length();

		if (start != -1) {
			int end = idWithIndex.indexOf(']', start);

			if (end != -1) {
				index = Integer.parseInt(idWithIndex.substring(start + 1, end));
				offset = start;
			}
		}

		procedureId = idWithIndex.substring(0, offset);

		resultType = arr[1];

	}

}
